package com.bridgeintelligent.tag.engine.mvc;

import com.bridgeintelligent.tag.engine.api.*;
import com.bridgeintelligent.tag.engine.api.rsp.*;
import com.bridgeintelligent.tag.engine.core.cache.CacheConfig;
import com.bridgeintelligent.tag.engine.core.cache.CacheUtils;
import com.bridgeintelligent.tag.engine.es.base.ESQueryUtils;
import com.bridgeintelligent.tag.engine.es.model.DataSetModel;
import com.bridgeintelligent.tag.engine.es.query.EsQueryBuilder;
import com.bridgeintelligent.tag.engine.mvc.service.IAnalysisAggregationService;
import com.bridgeintelligent.tag.engine.mvc.service.IEsDateService;
import com.bridgeintelligent.tag.engine.parse.DataSetParse;
import com.bridgeintelligent.tag.engine.parse.IndexParse;
import com.bridgeintelligent.tag.engine.parse.MicroPortraitParse;
import com.bridgeintelligent.tag.utils.FieldHandler;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.Strings;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by JackCheung on 2019/9/24 5:08 PM.
 */
@AllArgsConstructor
@Service
@Slf4j
public class EngineQueryService implements IEngineQueryService {

    public static final String DATE_FORMAT = "%s_%s";

    @Autowired
    private IEsDateService dateService;
    @Autowired
    private IAnalysisAggregationService aggregationService;

    /**
     * 数据集查询
     *
     * @param queryModel queryModel
     * @return DataSetRsp
     */
    @Override
    public DataSetRsp dataSet(QueryModel queryModel) {
        //封装查询数据
        DataSetModel dataSetModel = new DataSetModel();
        dataSetModel.setFrom(queryModel.getFrom());
        dataSetModel.setSize(queryModel.getSize());

        Map<String, String> relation = dateService.symbolRelation(queryModel.getIndexId());
        //list转set,过滤重复字段
        List<String> fieldsSet = fetchDateField(queryModel.getFields(), queryModel.getFieldsDataDate(),relation);
        String[] includes = new String[fieldsSet.size()];
        //设置包含项
        dataSetModel.setIncludes(fieldsSet.toArray(includes));
        //设置排除项，排除项为空
        dataSetModel.setExcludes(Strings.EMPTY_ARRAY);
        //将FilterGroup转换为QueryBuilder,然后给dataSetModel设值
        dataSetModel.setQueryBuilder(EsQueryBuilder.buildFilter(queryModel.getFilterGroup()));
        //排序
        if(StringUtils.isNotBlank(queryModel.getSortColumn())){
            String key = getSortKey(queryModel.getSortColumn(), queryModel.getFieldsDataDate(),relation);
            SortBuilder<FieldSortBuilder> sortBuilder;
            if(queryModel.isSort()){
                sortBuilder = SortBuilders.fieldSort(key).order(SortOrder.ASC);
            }else{
                sortBuilder = SortBuilders.fieldSort(key).order(SortOrder.DESC);
            }
            dataSetModel.setSortBuilder(sortBuilder);
        }

        IndexNameInfo indexNameInfo = CacheUtils.getCacheInfo(CacheConfig.CONFIGURATION_INFO, queryModel.getIndexId());
        DataSetRsp dataSetRsp = DataSetParse.create(queryModel, ESQueryUtils.dataSetSearch(indexNameInfo.getDataDate(), dataSetModel), fieldsSet);
        return fetchDate(dataSetRsp, queryModel);
    }

    private  DataSetRsp fetchDate(DataSetRsp dataSetRsp, QueryModel queryModel) {
        String date = queryModel.getFieldsDataDate();
        //如果日期不为纯数字，需要找到后缀对应的数据日期
        if (!FieldHandler.pattern.matcher(date).matches() ){
            date = dateService.findSymbolByDate(queryModel.getIndexId(),date);
        }
        String finalDate = StringUtils.isNotEmpty(date) && date.length() > 6 ? date : String.format(DATE_FORMAT, StringUtils.substring(date, 0, 4), StringUtils.substring(date, 4));
        dataSetRsp.getData()
                .getContent()
                .forEach(map -> map.put("queryDate", finalDate));
        return dataSetRsp;
    }




    private String getSortKey(String field, String dataDate,Map<String, String> relationMap){
        return FieldHandler.addSuffixField(field,dataDate,relationMap);
    }
    private List<String> fetchDateField(List<String> fieldsSet, String dataDate,Map<String, String> relationMap) {
        return fieldsSet.stream()
                        .map(s -> {
                            return FieldHandler.addSuffixField(s,dataDate, relationMap);
                        })
                        .collect(Collectors.toList());
    }

    /**
     * 聚合分析
     *
     * @param indexQueryModel indexQueryModel
     * @return IndexRsp
     */
    @Override
    public IndexRsp index(IndexModel indexQueryModel) {
        com.bridgeintelligent.tag.engine.es.model.IndexModel indexModel = new com.bridgeintelligent.tag.engine.es.model.IndexModel();
        indexModel.setQueryBuilder(EsQueryBuilder.buildFilter(indexQueryModel.getFilterGroup()));
        List<String> fields = indexQueryModel.getDims()
                                             .stream()
                                             .map(DimsDto::getDimId)
                                             .collect(Collectors.toList());
        indexModel.setAggregationBuilder(EsQueryBuilder.buildIndex(fields));
        //获取索引名
        String indexTemple = StringUtils.substringBefore(CacheUtils.getCacheInfo(CacheConfig.CONFIGURATION_INFO, CacheConfig.INDEX_NAME), "_");
        String[] indexNameStr = indexQueryModel.getQueryDate()
                                               .split(",");
        for (int i = 0; i < indexNameStr.length; i++) {
            indexNameStr[i] = String.format(INDEX_NAME_FORMAT, indexTemple, indexNameStr[i]);
        }
        return IndexParse.create(ESQueryUtils.indexSearch(indexModel, indexNameStr), fields);
    }

    @Override
    public CustomerGroupRsp customerGroup(QueryModel queryModel) throws IOException {

        IndexNameInfo indexNameInfo = CacheUtils.getCacheInfo(CacheConfig.CONFIGURATION_INFO, queryModel.getIndexId());
        SearchRequest searchRequest = new SearchRequest(indexNameInfo.getDataDate());
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        QueryBuilder queryBuilder;
        if (queryModel.isFieldTimeType()){
            queryBuilder = QueryBuilders.termsQuery(FieldHandler.CUSTOMER_FLAG,queryModel.getCustomersId());
        }else{
            queryBuilder = EsQueryBuilder.buildFilter(queryModel.getFilterGroup());
        }
        sourceBuilder.query(queryBuilder).trackTotalHits(true).size(0);
        log.info("customerGroup查询条件为----->>>>>{}", sourceBuilder);
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = ESQueryUtils.getClient().search(searchRequest, RequestOptions.DEFAULT);
        long totalCount = 0L;
        if (searchResponse != null){
            SearchHits hits = searchResponse.getHits();
            if (hits != null){
                TotalHits totalHits = hits.getTotalHits();
                if (totalHits != null){
                    totalCount = totalHits.value;
                }
            }
        }
        //allCount
        long allCount = aggregationService.getAllCount(queryModel.getIndexId());
        //percent
        String percent = aggregationService.compute(totalCount,allCount);
        CustomerGroupRsp customerGroupRsp = new CustomerGroupRsp();
        CustomerGroupRsp.DataRsp dataRsp = new CustomerGroupRsp.DataRsp();
        dataRsp.setTotalCount(totalCount);
        dataRsp.setPercent(percent);
        customerGroupRsp.setData(dataRsp);
        customerGroupRsp.setCode(BaseCode.SUCCESS);
        return customerGroupRsp;
    }

    /**
     * 微观画像
     *
     * @param filterName  filterName
     * @param filterValue filterValue
     * @return MicroPortraitRsp
     */
    @Override
    public MicroPortraitRsp microPortrait(String filterName, String filterValue) {
        Set<String> fieldsSet = new HashSet<>(CacheUtils.getCacheMap(CacheConfig.DIM_INFO)
                                                        .keySet());
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery(filterName, filterValue));
        DataSetModel dataSetModel = createModel(fieldsSet, queryBuilder);
        IndexNameInfo indexNameInfo = CacheUtils.getCacheInfo(CacheConfig.CONFIGURATION_INFO, "1");
        //根据索引ID查询symbols集
        String symbols = dateService.indexAllEsSymbol("1");

        return MicroPortraitParse.create(ESQueryUtils.dataSetSearch(indexNameInfo.getDataDate(), dataSetModel), fieldsSet,symbols);
    }

    @Override
    public MappingRsp getIndexMapping(String indexName) {
        Set<String> indexMapping = ESQueryUtils.getIndexMapping(indexName);
        return  new MappingRsp().setCode(0).setData(indexMapping);
    }

    /**
     * 创建DataSetModel对象
     *
     * @param fieldsSet    fieldsSet
     * @param queryBuilder queryBuilder
     * @return DataSetModel
     */
    private DataSetModel createModel(Set<String> fieldsSet, BoolQueryBuilder queryBuilder) {
        DataSetModel dataSetModel = new DataSetModel();
        dataSetModel.setSize(1);
        dataSetModel.setFrom(0);
        dataSetModel.setQueryBuilder(queryBuilder);
        return dataSetModel;
    }
}
